﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using HML.Design;
using System.Reflection;

namespace HML
{
    /// <summary>
    /// 主题面板弹层NativeWindow
    /// 
    /// 提供窗口句柄和窗口过程的低级封装
    /// NativeWindow 使用局部鼠标钩子来处理鼠标事件，放弃原有鼠标默认鼠标事件，因为要添加窗体自动消失功能，
    /// 使用分层窗体为例能绘制透明，同时在工作区域模拟非工作区部分。
    /// 
    /// </summary>
    [Description("主题面板弹层NativeWindow")]
    [DefaultProperty("DateValue")]
    [DefaultEvent("ItemClick")]
    [ToolboxItem(false)]
    public class SkinPicker : NativeWindow, IDisposable, IDpiControl, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(SkinPicker)).GetName().Name, typeof(SkinPicker).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        private SkinController skinController = null;
        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinController SkinController
        {
            get { return this.skinController; }
            set
            {
                if (this.skinController == value)
                    return;

                if (this.skinController != null)
                    this.skinController.RemoveSkinObject(this);

                this.skinController = value;

                if (this.skinController != null)
                    this.skinController.AddSkinObject(this);
            }
        }

        private SkinEnabledState skinEnabled = SkinEnabledState.Auto;
        /// <summary>
        /// 主题是否启用
        /// </summary>
        [Description("主题是否启用")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.Auto)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;
                this.OnSkinChanged();
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;
                this.OnSkinChanged();
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [PropertyOrder(-200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);

                return this.stateAppearance;
            }
        }

        /// <summary>
        /// 主题已更改
        /// </summary>
        public virtual void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);
            this.Invalidate();
        }

        private ISkinObject followSkinObject = null;
        /// <summary>
        /// 主题设置跟随指定主题对象（自己的设置不再生效，提供给代码使用）
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ISkinObject FollowSkinObject
        {
            get { return this.followSkinObject; }
            set
            {
                if (this.followSkinObject == value)
                    return;

                this.followSkinObject = value;
                this.OnSkinChanged();
            }
        }

        public virtual bool GetSkinObjectSkinStateCore()
        {
            return SkinManager.GetSkinObjectSkinState(this.FollowSkinObject ?? this);
        }

        void ISkinObject.InitializeInvalidate()
        {
            throw new NotImplementedException();
        }

        void ISkinObject.Invalidate()
        {
            this.Invalidate();
        }

        #endregion

        #region Dpi

        private float scaleDpi = 1.0f;
        /// <summary>
        /// 控件当前缩放Dpi
        /// </summary>
        [Description("控件当前缩放Dpi")]
        [Browsable(false)]
        [Localizable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual float ScaleDpi
        {
            get { return this.scaleDpi; }
            set
            {
                if (value <= 0)
                    return;

                this.scaleDpi = value;
                this.OnScaleDpiChangedInitialize();
            }
        }

        /// <summary>
        /// 控件DPI更改后重新初始化控件Rectangle信息
        /// </summary>
        protected void OnScaleDpiChangedInitialize()
        {
            this.Invalidate();
        }

        protected override void OnHandleChange()
        {
            base.OnHandleChange();


            IntPtr hDC = IntPtr.Zero;
            Graphics g = null;
            ControlHelper.GetWindowClientGraphics(this.Handle, out g, out hDC);

            float dpi = g.DpiX / 96f;

            g.Dispose();
            NativeMethods.ReleaseDC(this.Handle, hDC);

            this.ScaleDpi = dpi;
        }

        #endregion

        #region 新增事件

        public delegate void SkinPickerItemClickEventHandler(object sender, SkinPickerItemClickEventArgs e);
        private event SkinPickerItemClickEventHandler itemClick;
        /// <summary>
        /// 选项单击事件
        /// </summary>
        [Description("选项单击事件")]
        public event SkinPickerItemClickEventHandler ItemClick
        {
            add { this.itemClick += value; }
            remove { this.itemClick -= value; }
        }

        #endregion

        #region 新增属性

        private Font font = null;
        /// <summary>
        /// 字体
        /// </summary>
        [Description("字体")]
        [PropertyOrder(-198)]
        public Font Font
        {
            get
            {
                if (this.font != null)
                {
                    return this.font;
                }
                return Control.DefaultFont;
            }
            set
            {
                if (Control.DefaultFont.Equals(value))
                {
                    this.font = null;
                    return;
                }

                this.font = value;
            }
        }
        private bool ShouldSerializeFont()
        {
            return (this.font != null && !this.font.Equals(Control.DefaultFont));
        }
        private void ResetFont()
        {
            this.font = null;
        }

        private int roundSize = 6;
        /// <summary>
        /// 圆角Size
        /// </summary>
        [Description("圆角Size")]
        [PropertyOrder(-196)]
        [DefaultValue(6)]
        public int RoundSize
        {
            get { return this.roundSize; }
            set
            {
                if (value < 1)
                    value = 1;
                if (this.roundSize == value)
                    return;

                this.roundSize = value;
                this.Invalidate();
            }
        }

        private int maxHeight = 0;
        /// <summary>
        /// 下拉面板最大高度（0为自动计算）
        /// </summary>
        [Description("下拉面板最大高度（0为自动计算）")]
        [PropertyOrder(-194)]
        [DefaultValue(0)]
        public int MaxHeight
        {
            get { return this.maxHeight; }
            set
            {
                if (this.maxHeight == value || value <= 0)
                    return;

                this.maxHeight = value;
                this.Invalidate();
            }
        }

        private string nullTipText = "";
        /// <summary>
        /// 空数据源提示文本
        /// </summary>
        [Description("空数据源提示文本")]
        [PropertyOrder(-192)]
        [DefaultValue("")]
        public string NullTipText
        {
            get { return this.nullTipText; }
            set
            {
                if (this.nullTipText == value)
                    return;

                this.nullTipText = value;
                this.Invalidate();
            }
        }

        private ScrollBarObject scrollBar;
        /// <summary>
        /// 滚动条
        /// </summary>
        [Description("滚动条")]
        [PropertyOrder(-188)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ScrollBarObject ScrollBar
        {
            get
            {
                if (this.scrollBar == null)
                    this.scrollBar = new ScrollBarObject(this);
                return this.scrollBar;
            }
        }

        private Dictionary<string, Color> itemsSourceCollection;
        /// <summary>
        /// 选项集合
        /// </summary>
        [PropertyOrder(-186)]
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Dictionary<string, Color> ItemsSource
        {
            get
            {
                if (this.itemsSourceCollection == null)
                    this.itemsSourceCollection = new Dictionary<string, Color>();
                return this.itemsSourceCollection;
            }
        }

        private string selectedItem = null;
        /// <summary>
        /// 已选中选项
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string SelectedItem
        {
            get
            {
                if (String.IsNullOrWhiteSpace(selectedItem))
                    return null;
                return this.selectedItem;
            }
            set
            {
                if (String.IsNullOrWhiteSpace(value))
                    value = null;

                if (value != null)
                {
                    if (this.ItemsSource.Keys.ToArray().Where(a => a == value).Count() == 0)
                        value = null;
                }

                this.selectedItem = value;
            }
        }

        /// <summary>
        /// 主题面板弹层的显示状态
        /// </summary>
        [Browsable(false)]
        public bool Visible
        {
            get
            {
                if (this.Handle == IntPtr.Zero)
                    return false;

                return NativeMethods.IsWindowVisible(this.Handle);
            }
        }

        /// <summary>
        /// 控件大小和位置（包括其非工作区元素）
        /// </summary>
        [Browsable(false)]
        public Rectangle Bounds
        {
            get
            {
                if (this.Handle == IntPtr.Zero)
                    return Rectangle.Empty;

                NativeMethods.RECT r = new NativeMethods.RECT();
                NativeMethods.GetWindowRect(this.Handle, ref r);
                return new Rectangle(r.left, r.top, r.right - r.left, r.bottom - r.top);
            }
        }

        /// <summary>
        /// 控件工作区域大小和位置（模仿）
        /// </summary>
        [Browsable(false)]
        protected Rectangle ClientBounds
        {
            get
            {
                if (this.Handle == IntPtr.Zero)
                    return Rectangle.Empty;

                Rectangle rect = this.Bounds;
                int scale_roundedCorner = (this.owner == null) ? 0 : (int)Math.Ceiling(this.RoundSize * this.ScaleDpi);
                return new Rectangle(scale_roundedCorner, (int)(scale_roundedCorner / 3f), rect.Width - scale_roundedCorner * 2, rect.Height - scale_roundedCorner * 2);
            }
        }

        /// <summary>
        /// 控件工作区域（模仿）
        /// </summary>
        [Browsable(false)]
        public Rectangle ClientRectangle
        {
            get
            {
                if (this.Handle == IntPtr.Zero)
                    return Rectangle.Empty;

                Rectangle rect = this.Bounds;
                int scale_roundedCorner = (this.owner == null) ? 0 : (int)Math.Ceiling(this.RoundSize * this.ScaleDpi);
                return new Rectangle(0, 0, rect.Width - scale_roundedCorner * 2, rect.Height - scale_roundedCorner * 2);
            }
        }

        /// <summary>
        /// 控件当前滚动条是否显示
        /// </summary>
        [Browsable(false)]
        public bool ScrollVisible
        {
            get
            {
                if (this.owner == null || this.Handle == IntPtr.Zero)
                    return false;

                return (this.GetItemsRealityHeight() > this.ClientRectangle.Height);
            }
        }

        #endregion

        #region 字段

        /// <summary>
        /// 主题面板弹层拥有者
        /// </summary>
        private object owner = null;

        /// <summary>
        /// 主题面板弹层拥有者bounds
        /// </summary>
        private Rectangle owner_bounds = Rectangle.Empty;

        /// <summary>
        /// 主题面板弹层四边阴影图片缓存
        /// </summary>
        private Bitmap shadow_image_tmp = null;


        /// <summary>
        /// 鼠标钩子拥有者
        /// </summary>
        private static SkinPicker hook_owner = null;
        /// <summary>
        /// 鼠标钩子回调函数
        /// </summary>
        private HookProc hook_callback = null;
        /// <summary>
        /// 钩子id集合
        /// </summary>
        private static ArrayList hook_id_array = new ArrayList();
        /// <summary>
        /// 钩子id
        /// </summary>
        private int hook_id = 0;
        /// <summary>
        /// 鼠标钩子回调委托
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        /// <summary>
        /// 鼠标钩子返回信息结构体
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public PointStruct pt;
            public int hwnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }
        /// <summary>
        /// 鼠标钩子坐标
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct PointStruct
        {
            public int X;
            public int Y;
        }


        /// <summary>
        /// 鼠标是否在控件模拟工作区范围内 (WndProc消息)
        /// </summary>
        private bool wndproc_ismousein = false;
        /// <summary>
        /// 鼠标是否在控件模拟工作区范围内按下过 (WndProc消息)
        /// </summary>
        private bool wndproc_mousepressed = false;


        /// <summary>
        /// 当前鼠标已按下的对象(-2 滚动条、-1没有、>=0 主题面板选项)
        /// </summary>
        private int mousedownindex = -1;
        /// <summary>
        /// 鼠标按下功能坐标
        /// </summary>
        private Point mousedownpoint = Point.Empty;
        /// <summary>
        /// 鼠标按下滚动条时菜单真实区的Y坐标
        /// </summary>
        private int mousedown_scrollOffsetY = 0;
        /// <summary>
        /// 鼠标进入对象
        /// </summary>
        private int mouseenterindex = -1;


        /// <summary>
        /// 滚动条轨道Rect
        /// </summary>
        public Rectangle scrollTrackRect = Rectangle.Empty;
        /// <summary>
        /// 滚动条拇指rect
        /// </summary>
        public Rectangle scrollThumbRect = Rectangle.Empty;
        /// <summary>
        /// 滚动条拇指Y轴距离(存放内容Y轴真实距离)
        /// </summary>
        private int scrollOffsetY = 0;

        /// <summary>
        /// 选项高度
        /// </summary>
        private int item_height = 0;
        /// <summary>
        /// 字体高度
        /// </summary>
        private int font_height = 0;
        /// <summary>
        /// 字体外边距
        /// </summary>
        private int font_margin = 0;
        /// <summary>
        /// 字体平局宽度
        /// </summary>
        private int font_charAveWidth = 0;

        #endregion

        #region 扩展

        private const int SWP_NOSIZE = 0x0001;
        private const int SWP_NOMOVE = 0x0002;
        private const int SWP_NOZORDER = 0x0004;
        private const int SWP_NOACTIVATE = 0x0010;
        private const int SWP_SHOWWINDOW = 0x0040;
        private const int SWP_HIDEWINDOW = 0x0080;
        private const int WM_GETOBJECT = 0x003D;
        private const int WM_SETCURSOR = 0x0020;
        private const int WM_MOUSEWHEEL = 0x020A;
        private const int WM_MOUSEACTIVATE = 0x0021;//鼠标激活窗体
        private const int MA_NOACTIVATE = 3;// 不激活窗口，但也不会放弃鼠标消息

        private const int WH_MOUSE = 14;
        private const int WM_LBUTTONDOWN = 0x0201;
        private const int WM_MBUTTONDOWN = 0x0207;
        private const int WM_RBUTTONDOWN = 0x0204;
        private const int WM_NCLBUTTONDOWN = 0x00A1;
        private const int WM_NCRBUTTONDOWN = 0x00A4;
        private const int WM_NCMBUTTONDOWN = 0x00A7;
        private const int WM_LBUTTONUP = 0x0202;
        private const int WM_MOUSEMOVE = 0x0200;

        private const int WS_CAPTION = 0x00C00000;
        private const int WS_CLIPSIBLINGS = 0x04000000;
        private const int WS_POPUP = unchecked((int)0x80000000);
        private const int WS_EX_APPWINDOW = 0x00040000;
        private const int WS_EX_CONTROLPARENT = 0x00010000;
        private const int WS_EX_TOOLWINDOW = 0x00000080;
        private const int WS_EX_LAYERED = 0x80000;
        private const int CS_SAVEBITS = 0x0800;
        private const int GWL_EXSTYLE = (-20);

        private const int ULW_ALPHA = 0x00000002;//使用 pblend 作為混合函式
        private const byte AC_SRC_OVER = 0;//定義要執行的混合作業
        private const byte AC_SRC_ALPHA = 1;//混合作業方式

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct BLENDFUNCTION
        {
            public byte BlendOp;
            public byte BlendFlags;
            public byte SourceConstantAlpha;
            public byte AlphaFormat;
        }

        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern int DeleteDC(IntPtr hdc);

        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr SelectObject(IntPtr hdc, IntPtr h);

        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern int DeleteObject(IntPtr ho);

        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern int UpdateLayeredWindow(IntPtr hWnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int hookid, HookProc pfnhook, IntPtr hinst, int threadid);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string modName);

        #endregion

        protected SkinPicker()
        {
            //设置弹层拥有者
            this.owner = null;

            //设置窗体样式（分层窗体、禁止出现在导航列表）
            CreateParams cp = new CreateParams();
            cp.Style &= ~(WS_CAPTION | WS_CLIPSIBLINGS);
            cp.ExStyle &= ~(WS_EX_APPWINDOW);
            cp.Style |= WS_POPUP;
            cp.ExStyle |= (WS_EX_CONTROLPARENT);
            cp.ExStyle |= WS_EX_LAYERED;
            cp.ClassStyle |= CS_SAVEBITS;

            //创建控件句柄
            this.CreateHandle(cp);

            //禁止出啊现在任务栏
            int flags = unchecked((int)(long)NativeMethods.GetWindowLong(this.Handle, GWL_EXSTYLE)) | WS_EX_TOOLWINDOW;
            NativeMethods.SetWindowLong(this.Handle, GWL_EXSTYLE, (IntPtr)flags);

            this.OnSkinChanged();
        }

        public SkinPicker(object owner)
        {
            //设置弹层拥有者
            this.owner = owner;

            //设置窗体样式（分层窗体、禁止出现在导航列表）
            CreateParams cp = new CreateParams();
            cp.Style &= ~(WS_CAPTION | WS_CLIPSIBLINGS);
            cp.ExStyle &= ~(WS_EX_APPWINDOW);
            cp.Style |= WS_POPUP;
            cp.ExStyle |= (WS_EX_CONTROLPARENT);
            cp.ExStyle |= WS_EX_LAYERED;
            cp.ClassStyle |= CS_SAVEBITS;

            //创建控件句柄
            this.CreateHandle(cp);

            //禁止出啊现在任务栏
            int flags = unchecked((int)(long)NativeMethods.GetWindowLong(this.Handle, GWL_EXSTYLE)) | WS_EX_TOOLWINDOW;
            NativeMethods.SetWindowLong(this.Handle, GWL_EXSTYLE, (IntPtr)flags);

            this.OnSkinChanged();

        }

        #region 重写

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            switch (m.Msg)
            {
                case WM_MOUSEACTIVATE://禁止激活窗体但接受鼠标事件
                    {
                        m.Result = new IntPtr(MA_NOACTIVATE);
                        return;
                    }
                case WM_MOUSEWHEEL://鼠标滚轮滚动
                    {
                        this.DefWndProc(ref m);

                        Point point = new Point(NativeMethods.SignedLOWORD(m.LParam), NativeMethods.SignedHIWORD(m.LParam));
                        this.WmMouseWheel(this.owner, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, (short)NativeMethods.SignedHIWORD(m.WParam)));

                        break;
                    }
                case NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEENTER:// 鼠标进入
                    {
                        Point point = new Point(NativeMethods.SignedLOWORD(m.LParam), NativeMethods.SignedHIWORD(m.LParam));
                        this.WmMouseEnter(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));

                        break;
                    }
                case NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSELEAVE:// 鼠标离开
                    {
                        Point point = new Point(NativeMethods.SignedLOWORD(m.LParam), NativeMethods.SignedHIWORD(m.LParam));
                        this.WmMouseLeave(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));

                        break;
                    }
                case NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEDOWN://鼠标左键按下
                    {
                        Point point = new Point(NativeMethods.SignedLOWORD(m.LParam), NativeMethods.SignedHIWORD(m.LParam));
                        this.WmMouseDown(this, new MouseEventArgs(MouseButtons.Left, 1, point.X, point.Y, 0));

                        break;
                    }
                case NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEUP://鼠标左键释放
                    {
                        Point point = new Point(NativeMethods.SignedLOWORD(m.LParam), NativeMethods.SignedHIWORD(m.LParam));
                        this.WmMouseUp(this, new MouseEventArgs(MouseButtons.Left, 1, point.X, point.Y, 0));

                        break;
                    }
                case NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEMOVE://鼠标移动
                    {
                        Point point = new Point(NativeMethods.SignedLOWORD(m.LParam), NativeMethods.SignedHIWORD(m.LParam));
                        this.WmMouseMove(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));

                        break;
                    }
                case NativeMethods.WM_USER_DROPDROWLISTPLUS_CLOSED://主题面板弹层关闭
                    {
                        this.WmClosed(this, EventArgs.Empty);

                        break;
                    }
                case NativeMethods.WM_USER_DROPDROWLISTPLUS_PAINT://绘制分层窗体
                    {
                        if (this.Handle != IntPtr.Zero && this.owner != null && this.Visible && this.Bounds.Width != 0 && this.Bounds.Height != 0)
                        {
                            //创建画布
                            Bitmap bmp = new Bitmap(this.Bounds.Width, this.Bounds.Height);
                            Graphics g = Graphics.FromImage(bmp);
                            //绘制（模仿非工作区）
                            PaintEventArgs nc_arg = new PaintEventArgs(g, new Rectangle(0, 0, this.Bounds.Width, this.Bounds.Height));
                            this.WmNCPaint(this, nc_arg);
                            //绘制（模仿工作区）
                            GraphicsPath client_path = new GraphicsPath();
                            client_path.AddPath(ControlHelper.AdjustCircularPath(this.ClientBounds, (int)Math.Ceiling(this.RoundSize * this.ScaleDpi)), true);

                            g.SetClip(client_path);
                            g.TranslateTransform(this.ClientBounds.X, this.ClientBounds.Y); //修改系统坐标为模仿工作区坐标
                            this.WmPaint(this, new PaintEventArgs(g, this.ClientRectangle));
                            g.ResetClip();
                            client_path.Dispose();
                            //绘制边框
                            this.WmBorderPaint(this, nc_arg);

                            //把画布图片绑定到分层窗体上
                            IntPtr hdcDst = GetDC(this.Handle);
                            IntPtr hdcSrc = CreateCompatibleDC(hdcDst);

                            IntPtr newBitmap = bmp.GetHbitmap(Color.FromArgb(0));//创建一张位图
                            IntPtr oldBitmap = SelectObject(hdcSrc, newBitmap);//位图绑定到DC设备上

                            Point pptDst = new Point(this.Bounds.Left, this.Bounds.Top);
                            Size psize = new Size(bmp.Width, bmp.Height);
                            Point pptSrc = new Point(0, 0);

                            BLENDFUNCTION pblend = new BLENDFUNCTION();
                            pblend.BlendOp = AC_SRC_OVER;
                            pblend.SourceConstantAlpha = 255;
                            pblend.AlphaFormat = AC_SRC_ALPHA;
                            pblend.BlendFlags = 0;

                            UpdateLayeredWindow(this.Handle, hdcDst, ref pptDst, ref psize, hdcSrc, ref pptSrc, 0, ref pblend, ULW_ALPHA);

                            SelectObject(hdcSrc, oldBitmap);
                            ReleaseDC(this.Handle, hdcDst);
                            DeleteObject(newBitmap);
                            DeleteDC(hdcSrc);


                            bmp.Dispose();
                            g.Dispose();
                        }

                        break;
                    }
                default:
                    {
                        this.DefWndProc(ref m);
                        break;
                    }
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                this.HookListenStop();
                if (this.shadow_image_tmp != null)
                {
                    this.shadow_image_tmp.Dispose();
                    this.shadow_image_tmp = null;
                }
                //清理托管资源
            }
            this.DestroyHandle();
            //清理非托管资源
        }

        #endregion

        #region 虚方法

        protected virtual void OnItemClick(SkinPickerItemClickEventArgs e)
        {
            if (this.itemClick != null)
            {
                this.itemClick(this, e);
            }
        }

        #endregion

        #region  公开方法

        /// <summary>
        /// 显示主题面板弹层(同时安装钩子)
        /// </summary>
        /// <param name="rect">要显示的参考rect（相对于屏幕坐标）</param>
        public void ShowPicker(Rectangle rect)
        {
            if (this.owner == null)
                return;
            this.owner_bounds = rect;
            this.wndproc_mousepressed = false;
            this.wndproc_ismousein = false;

            NativeMethods.TEXTMETRIC font_metrics = ControlHelper.GetFontMetrics(this.Handle, this.Font);
            this.font_height = font_metrics.GetFontRealHeight();
            this.font_margin = font_metrics.GetFontStereotypesMargim();
            this.font_charAveWidth = font_metrics.tmAveCharWidth;

            this.item_height = this.font_height + this.font_height + this.font_height;

            Rectangle bounds = this.AdjustBounds();
            if (this.shadow_image_tmp != null)
            {
                this.shadow_image_tmp.Dispose();
            }
            this.shadow_image_tmp = this.CreateShadowBitmap(bounds.Width, bounds.Height);

            NativeMethods.SetWindowPos(this.Handle, IntPtr.Zero, bounds.X, bounds.Y, bounds.Width, bounds.Height, SWP_NOACTIVATE | SWP_SHOWWINDOW);

            this.SetScrollOffsetY(0);
            this.Invalidate();

            this.HookListenStart();
        }

        /// <summary>
        /// 隐藏主题面板弹层(同时取消钩子)
        /// </summary>
        public void HidePicker()
        {
            this.HideView();
            this.HookListenStop();
        }

        /// <summary>
        /// 绘制主题面板弹层
        /// </summary>
        public void Invalidate()
        {
            NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_PAINT, (IntPtr)0, (IntPtr)0);
        }

        /// <summary>
        /// 设置滚动条拇指Y轴距离
        /// </summary>
        /// <param name="y"></param>
        public void SetScrollOffsetY(int y)
        {
            if (!this.ScrollVisible)
            {
                if (this.scrollOffsetY != 0)
                {
                    this.scrollOffsetY = 0;
                    this.AdjustScrollRectangle();
                    this.Invalidate();
                }
                return;
            }

            int itemsRealityHeight = this.GetItemsRealityHeight();

            int new_y = y;
            if (new_y < this.ClientRectangle.Height - itemsRealityHeight)
            {
                new_y = this.ClientRectangle.Height - itemsRealityHeight;
            }
            if (new_y > 0)
            {
                new_y = 0;
            }

            int old_y = this.scrollOffsetY;
            this.scrollOffsetY = new_y;
            this.AdjustScrollRectangle();

            if (old_y != new_y)
            {
                this.Invalidate();
            }
        }

        /// <summary>
        /// 将指定屏幕点的位置计算成工作区坐标
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public Point PointToClient(Point point)
        {
            Rectangle bounds = this.Bounds;
            return new Point(point.X - (bounds.X + this.ClientBounds.X), point.Y - (bounds.Y + this.ClientBounds.Y));
        }

        /// <summary>
        /// 将指定工作区点的位置计算成屏幕坐标
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public Point PointToScreen(Point point)
        {
            Rectangle bounds = this.Bounds;
            return new Point((bounds.X + this.ClientBounds.X) + point.X, (bounds.Y + this.ClientBounds.Y) + point.Y);
        }

        /// <summary>
        /// 鼠标是否进入选项
        /// </summary>
        /// <param name="index">选项索引</param>
        /// <returns></returns>
        public bool IsMouseEnter(int index)
        {
            return (index != -1 && this.mousedownindex == index);
        }

        /// <summary>
        /// 显式调用
        /// </summary>
        public void Dispose()
        {
            Dispose(true);//释放托管和非托管资源
            System.GC.SuppressFinalize(this);//阻止GC调用析构函数
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 计算主题面板弹层显示区域Bounds
        /// </summary>
        private Rectangle AdjustBounds()
        {
            if (this.owner == null)
                return Rectangle.Empty;

            Rectangle screen_rect = Screen.FromHandle(this.Handle).WorkingArea;
            int scale_roundSize = (int)Math.Ceiling(this.RoundSize * this.ScaleDpi);
            int scale_nativeWindow_client_width = this.GetItemWidth();
            int scale_nativeWindow_client_height = this.GetItemsRealityHeight();
            if (this.MaxHeight > 0)
            {
                scale_nativeWindow_client_height = Math.Min(scale_nativeWindow_client_height, (int)Math.Ceiling(this.MaxHeight * this.ScaleDpi));
            }

            int nativeWindow_y = this.owner_bounds.Bottom;//下拉框Top默认位置
            if (nativeWindow_y + scale_roundSize + scale_nativeWindow_client_height + scale_roundSize > screen_rect.Bottom)//下拉框高度超过屏幕底部
            {
                if (this.owner_bounds.Y > screen_rect.Height * 3 / 4)//下拉框Top默认位置在屏幕高度3/4下面
                {
                    if (owner_bounds.Y - scale_roundSize - scale_nativeWindow_client_height - scale_roundSize - 10 < 0)
                    {
                        scale_nativeWindow_client_height = this.owner_bounds.Y - scale_roundSize - scale_roundSize - 10;//下拉框高度不能超过屏幕顶部
                        if (this.MaxHeight > 0)
                        {
                            scale_nativeWindow_client_height = Math.Min(scale_nativeWindow_client_height, (int)Math.Ceiling(this.MaxHeight * this.ScaleDpi));
                        }
                    }
                    nativeWindow_y = this.owner_bounds.Y - scale_roundSize - scale_nativeWindow_client_height - scale_roundSize;//下拉框改为Bottom默认位置
                }
                else
                {
                    scale_nativeWindow_client_height = screen_rect.Bottom - nativeWindow_y - scale_roundSize - scale_roundSize;//下拉框高度不能超过屏幕底部
                    if (this.MaxHeight > 0)
                    {
                        scale_nativeWindow_client_height = Math.Min(scale_nativeWindow_client_height, (int)Math.Ceiling(this.MaxHeight * this.ScaleDpi));
                    }
                }
            }

            return new Rectangle(this.owner_bounds.Right - (scale_roundSize + scale_nativeWindow_client_width + scale_roundSize), nativeWindow_y, scale_roundSize + scale_nativeWindow_client_width + scale_roundSize, scale_roundSize + scale_nativeWindow_client_height + scale_roundSize);

        }

        /// <summary>
        /// 更新主题面板弹层滚动条Rect
        /// </summary>
        private void AdjustScrollRectangle()
        {
            int itemsRealityHeight = this.GetItemsRealityHeight();
            int scale_roundedCorner = (int)Math.Ceiling(this.RoundSize * this.ScaleDpi);
            int scale_scrollThickness = this.ScrollVisible ? (int)Math.Ceiling(this.ScrollBar.TrackThickness * this.ScaleDpi) : 0;
            int scale_scrollThumbMinSize = (int)Math.Ceiling(this.ScrollBar.ThumbMinSize * this.ScaleDpi);

            this.scrollTrackRect = new Rectangle(this.ClientRectangle.Right - scale_scrollThickness, this.ClientRectangle.Y + scale_roundedCorner, scale_scrollThickness, this.ClientRectangle.Height - scale_roundedCorner * 2);

            int thumb_height = (int)Math.Max(Math.Min(this.scrollTrackRect.Height, scale_scrollThumbMinSize), this.scrollTrackRect.Height * ((float)this.ClientRectangle.Height / (float)itemsRealityHeight));
            int thumb_y = (int)(this.scrollTrackRect.Y + (this.scrollTrackRect.Height - thumb_height) * (-this.scrollOffsetY / (float)(itemsRealityHeight - this.ClientRectangle.Height)));
            this.scrollThumbRect = new Rectangle(this.ClientRectangle.Right - scale_scrollThickness, thumb_y, scale_scrollThickness, thumb_height);
        }

        /// <summary>
        /// 获取列表真实高度
        /// </summary>
        /// <returns></returns>
        private int GetItemsRealityHeight()
        {
            return ((this.owner == null || this.ItemsSource.Count == 0) ? 1 : this.ItemsSource.Count) * this.item_height;
        }

        /// <summary>
        /// 获取选项宽度
        /// </summary>
        /// <returns></returns>
        private int GetItemWidth()
        {
            int len = string.IsNullOrWhiteSpace(this.nullTipText) ? 0 : this.nullTipText.Length;
            foreach (KeyValuePair<string, Color> item in this.ItemsSource)
            {
                if (item.Key.Length > len)
                    len = item.Key.Length;
            }
            return Math.Max(len * this.font_charAveWidth, this.item_height * 10);
        }

        /// <summary>
        /// 获取进入工作区的第一个选项索引
        /// </summary>
        /// <returns></returns>
        private int GetClientRectangleFirstIndex()
        {
            if (-this.scrollOffsetY < this.item_height)
                return 0;
            else
                return -this.scrollOffsetY / this.item_height;
        }

        /// <summary>
        /// 根据坐标查找选项索引
        /// </summary>
        /// <param name="point">相对于控件模拟工作区坐标</param>
        /// <returns></returns>
        private int FindItemIndexForPoint(Point point)
        {
            if (this.ItemsSource.Count == 0 || !this.ClientRectangle.Contains(point))
                return -1;

            if (this.ScrollVisible && this.scrollTrackRect.Contains(point))
                return -1;

            point.Y += -this.scrollOffsetY;

            return (int)Math.Ceiling(point.Y / (float)this.item_height) - 1;

        }

        /// <summary>
        /// 隐藏窗体（只隐藏不作任何其他处理）
        /// </summary>
        private void HideView()
        {
            this.wndproc_mousepressed = false;
            this.wndproc_ismousein = false;
            NativeMethods.SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
        }

        /// <summary>
        /// 创建带阴影边框图片
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private Bitmap CreateShadowBitmap(int width, int height)
        {
            Color shadow_color = this.StyleAppearance.ShadowColor;
            int roundedCorner = (int)Math.Ceiling(this.RoundSize * this.ScaleDpi);
            int shadowSize = roundedCorner * 2;

            Bitmap bmp = new Bitmap(width, height);

            //上
            for (int x = shadowSize; x < width - shadowSize; x++)
            {
                for (int y = 0; y < shadowSize; y++)
                {
                    int proportion = (int)(255 * Math.Min(1, EaseBothCore((shadowSize - y) / (double)shadowSize, 2)));
                    Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                    bmp.SetPixel(x, shadowSize - y, nColor);
                }
            }
            ////下
            for (int x = shadowSize; x < width - shadowSize; x++)
            {
                for (int y = 0; y < shadowSize; y++)
                {
                    int proportion = (int)(255 * Math.Min(1, EaseInCore((shadowSize - y) / (double)shadowSize, 2)));
                    Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                    bmp.SetPixel(x, height - shadowSize + y, nColor);
                }
            }
            //左
            for (int y = shadowSize; y < height - shadowSize; y++)
            {
                for (int x = 0; x < shadowSize; x++)
                {
                    int proportion = (int)(255 * Math.Min(1, EaseBothCore((shadowSize - x) / (double)shadowSize, 2)));
                    Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                    bmp.SetPixel(shadowSize - x, y, nColor);
                }
            }
            //右
            for (int y = shadowSize; y < height - shadowSize; y++)
            {
                for (int x = 0; x < shadowSize; x++)
                {
                    int proportion = (int)(255 * Math.Min(1, EaseBothCore((shadowSize - x) / (double)shadowSize, 2)));
                    Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                    bmp.SetPixel(width - shadowSize + x, y, nColor);
                }
            }
            //左上
            {
                Point center = new Point(shadowSize, shadowSize);
                for (int x = shadowSize; x >= 0; x--)
                {
                    for (int y = shadowSize; y >= 0; y--)
                    {
                        int tmp = (int)Math.Sqrt(Math.Pow(x - center.X, 2) + Math.Pow(y - center.Y, 2));
                        if (tmp <= shadowSize)
                        {
                            int proportion = (int)(255 * EaseBothCore((shadowSize - tmp) / (double)shadowSize, 2));
                            Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                            bmp.SetPixel(x, y, nColor);
                        }
                    }
                }
            }
            //右上
            {
                Point center = new Point(width - shadowSize, shadowSize);
                for (int x = width - shadowSize; x < width; x++)
                {
                    for (int y = shadowSize; y >= 0; y--)
                    {
                        int tmp = (int)Math.Sqrt(Math.Pow(x - center.X, 2) + Math.Pow(y - center.Y, 2));
                        if (tmp <= shadowSize)
                        {
                            int proportion = (int)(255 * EaseBothCore((shadowSize - tmp) / (double)shadowSize, 2));
                            Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                            bmp.SetPixel(x, y, nColor);
                        }
                    }
                }
            }
            //右下
            {
                Point center = new Point(width - shadowSize, height - shadowSize);
                for (int x = width - shadowSize; x < width; x++)
                {
                    for (int y = height - shadowSize; y < height; y++)
                    {
                        int tmp = (int)Math.Sqrt(Math.Pow(x - center.X, 2) + Math.Pow(y - center.Y, 2));
                        if (tmp <= shadowSize)
                        {
                            int proportion = (int)(255 * EaseInCore((shadowSize - tmp) / (double)shadowSize, 2));
                            Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                            bmp.SetPixel(x, y, nColor);
                        }
                    }
                }
            }
            //左下
            {
                Point center = new Point(shadowSize, height - shadowSize);
                for (int x = shadowSize; x >= 0; x--)
                {
                    for (int y = height - shadowSize; y < height; y++)
                    {
                        int tmp = (int)Math.Sqrt(Math.Pow(x - center.X, 2) + Math.Pow(y - center.Y, 2));
                        if (tmp <= shadowSize)
                        {
                            int proportion = (int)(255 * EaseInCore((shadowSize - tmp) / (double)shadowSize, 2));
                            Color nColor = Color.FromArgb(proportion, shadow_color.R, shadow_color.G, shadow_color.B);
                            bmp.SetPixel(x, y, nColor);
                        }
                    }
                }
            }

            return bmp;
        }

        /// <summary>
        /// EaseIn动画函数
        /// </summary>
        /// <param name="progress">进度百分值</param>
        /// <param name="power">曲线幂</param>
        /// <returns></returns>
        private double EaseInCore(double progress, double power)
        {
            power = Math.Max(0.0, power);
            return Math.Pow(progress, power);
        }

        /// <summary>
        /// EaseBoth动画函数
        /// </summary>
        /// <param name="progress">进度百分值</param>
        /// <param name="power">曲线幂</param>
        /// <returns></returns>
        private double EaseBothCore(double progress, double power)
        {
            if (progress >= 0.5)
                return (1.0 - EaseInCore((1.0 - progress) * 2.0, power)) * 0.5 + 0.5;
            return EaseInCore(progress * 2.0, power) * 0.5;
        }

        /// <summary>
        /// 开始监听钩子
        /// </summary>
        private void HookListenStart()
        {
            if (hook_owner != this)
            {
                if (this.hook_id != 0)
                {
                    if (!UnhookWindowsHookEx(this.hook_id))
                    {
                        throw new Exception("SkinPicker 取消鼠标钩子失败");
                    }

                    hook_id_array.Remove(this.hook_id);
                    this.hook_id = 0;

                    Debug.Print("取消 mousehook handle:" + this.Handle.ToString() + " hook_id:" + this.hook_id.ToString() + " visible:" + this.Visible.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));
                }
                if (hook_owner != null)
                {
                    hook_owner.HideView();
                }
            }

            if (this.hook_id == 0)
            {
                if (this.hook_callback == null)
                {
                    this.hook_callback = new HookProc(this.MouseHookProc);
                }
                this.hook_id = SetWindowsHookEx(WH_MOUSE, this.hook_callback, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
                if (this.hook_id == 0)
                {
                    throw new Exception("SkinPicker 安装鼠标钩子失败");
                }
                else
                {
                    Debug.Print("安装 mousehook handle:" + this.Handle.ToString() + " hook_id:" + this.hook_id.ToString() + " visible:" + this.Visible.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

                    hook_id_array.Add(this.hook_id);
                    hook_owner = this;
                }
            }
        }
        /// <summary>  
        /// 结束监听钩子  
        /// </summary>  
        private void HookListenStop()
        {
            if (hook_owner == this)
            {
                hook_owner = null;
                if (this.hook_id != 0)
                {
                    if (!UnhookWindowsHookEx(this.hook_id))
                    {
                        throw new Exception("SkinPicker 取消鼠标钩子失败");
                    }
                    hook_id_array.Remove(this.hook_id);
                    this.hook_id = 0;

                    Debug.Print("取消 mousehook handle:" + this.Handle.ToString() + " hook_id:" + this.hook_id.ToString() + " visible:" + this.Visible.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));
                }
            }
        }
        /// <summary>
        /// 利用钩子处理鼠标事件
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            Debug.Print("mousehook handle:" + this.Handle.ToString() + " hook_id:" + this.hook_id.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

            switch (unchecked((int)(long)wParam))
            {
                //关闭主题面板弹层
                case WM_RBUTTONDOWN:
                case WM_MBUTTONDOWN:
                case WM_NCLBUTTONDOWN:
                case WM_NCRBUTTONDOWN:
                case WM_NCMBUTTONDOWN:
                    {
                        // Point client_point = this.PointToClient(this.GetMouseHookStructMousePosition(lParam));
                        Point client_point = this.PointToClient(Control.MousePosition);
                        if (!this.ClientRectangle.Contains(client_point) && this.Visible)
                        {
                            this.wndproc_mousepressed = false;
                            this.wndproc_ismousein = false;
                            NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_CLOSED, (IntPtr)0, (IntPtr)0);
                        }
                        break;
                    }
                //关闭主题面板弹层、鼠标按下
                case WM_LBUTTONDOWN:
                    {
                        // Point client_point = this.PointToClient(this.GetMouseHookStructMousePosition(lParam));
                        Point client_point = this.PointToClient(Control.MousePosition);
                        if (!this.ClientRectangle.Contains(client_point))
                        {
                            if (this.Visible)
                            {
                                this.wndproc_mousepressed = false;
                                this.wndproc_ismousein = false;
                                NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_CLOSED, (IntPtr)0, (IntPtr)0);
                            }
                        }
                        else
                        {
                            this.wndproc_mousepressed = true;
                            this.wndproc_ismousein = true;
                            NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEDOWN, (IntPtr)0, NativeMethods.MAKELPARAM(client_point.X, client_point.Y));
                        }
                        break;
                    }
                //鼠标按下释放、鼠标离开失焦
                case WM_LBUTTONUP:
                    {
                        if (this.wndproc_mousepressed)
                        {
                            // Point client_point = this.PointToClient(this.GetMouseHookStructMousePosition(lParam));
                            Point client_point = this.PointToClient(Control.MousePosition);
                            this.wndproc_mousepressed = false;
                            NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEUP, (IntPtr)0, NativeMethods.MAKELPARAM(client_point.X, client_point.Y));
                            if (!this.ClientRectangle.Contains(client_point))
                            {
                                this.wndproc_ismousein = false;
                                NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSELEAVE, (IntPtr)0, NativeMethods.MAKELPARAM(client_point.X, client_point.Y));
                            }
                        }
                        break;
                    }
                //鼠标进入、鼠标移动、鼠标离开失焦
                case WM_MOUSEMOVE:
                    {
                        // Point client_point = this.PointToClient(this.GetMouseHookStructMousePosition(lParam));
                        Point client_point = this.PointToClient(Control.MousePosition);
                        if (this.wndproc_mousepressed)
                        {
                            NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEMOVE, (IntPtr)0, NativeMethods.MAKELPARAM(client_point.X, client_point.Y));
                        }
                        else
                        {
                            if (this.wndproc_ismousein)
                            {
                                if (!this.ClientRectangle.Contains(client_point))
                                {
                                    this.wndproc_ismousein = false;
                                    NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSELEAVE, (IntPtr)0, NativeMethods.MAKELPARAM(client_point.X, client_point.Y));
                                }
                                else
                                {
                                    NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEMOVE, (IntPtr)0, NativeMethods.MAKELPARAM(client_point.X, client_point.Y));
                                }
                            }
                            else
                            {
                                if (this.ClientRectangle.Contains(client_point))
                                {
                                    this.wndproc_ismousein = true;
                                    NativeMethods.SendMessage(this.Handle, NativeMethods.WM_USER_DROPDROWLISTPLUS_MOUSEENTER, (IntPtr)0, NativeMethods.MAKELPARAM(client_point.X, client_point.Y));
                                }
                            }
                        }
                    }
                    break;
            }

            return CallNextHookEx(this.hook_id, nCode, wParam, lParam);
        }
        /// <summary>
        /// 获取控件鼠标钩子鼠标坐标(相对于屏幕)
        /// </summary>
        /// <returns></returns>
        private Point GetMouseHookStructMousePosition(IntPtr lParam)
        {
            MouseHookStruct mhs = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
            return new Point(mhs.pt.X, mhs.pt.Y);
        }

        /// <summary>
        /// 鼠标进入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmMouseEnter(object sender, MouseEventArgs e)
        {
            Debug.Print("MouseEnter " + e.Location.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

            this.WmMouseMove(sender, e);
        }
        /// <summary>
        /// 鼠标离开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmMouseLeave(object sender, MouseEventArgs e)
        {
            Debug.Print("MouseLeave " + e.Location.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

            this.mousedownindex = -1;
            this.mouseenterindex = -1;
            this.Invalidate();
        }
        /// <summary>
        /// 鼠标按下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmMouseDown(object sender, MouseEventArgs e)
        {
            Debug.Print("MouseDown " + e.Location.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

            if (this.ScrollVisible && this.scrollTrackRect.Contains(e.Location))
            {
                if (this.scrollThumbRect.Contains(e.Location))
                {
                    this.mousedownindex = -2;
                    this.mousedownpoint = e.Location;
                    this.mousedown_scrollOffsetY = this.scrollOffsetY;
                }
                else
                {
                    this.mousedownindex = -1;
                }
            }
            else
            {
                this.mousedownindex = this.FindItemIndexForPoint(e.Location);
            }

        }
        /// <summary>
        /// 鼠标释放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmMouseUp(object sender, MouseEventArgs e)
        {
            Debug.Print("MouseUp " + e.Location.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

            if (this.mousedownindex >= 0)
            {
                int index = this.FindItemIndexForPoint(e.Location);
                if (index != -1 && this.mousedownindex == index)
                {
                    this.selectedItem = this.ItemsSource.Keys.ToArray()[index];
                    this.HidePicker();
                    this.mousedownindex = -1;

                    SkinPickerItemClickEventArgs arg = new SkinPickerItemClickEventArgs(this.selectedItem);
                    this.OnItemClick(arg);
                }
            }
            this.mousedownindex = -1;

        }
        /// <summary>
        /// 鼠标移动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmMouseMove(object sender, MouseEventArgs e)
        {
            Debug.Print("MouseMove " + e.Location.ToString() + " " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

            if (this.mousedownindex != -1)
            {
                if (this.mousedownindex == -2)//拖动滚动条
                {
                    int itemsRealityHeight = this.GetItemsRealityHeight();

                    int new_y = this.mousedown_scrollOffsetY - (int)((itemsRealityHeight - this.ClientRectangle.Height) * (e.Location.Y - this.mousedownpoint.Y) / (float)(this.scrollTrackRect.Height - this.scrollThumbRect.Height));
                    this.SetScrollOffsetY(new_y);
                }
            }
            else
            {
                int index = this.FindItemIndexForPoint(e.Location);
                if (this.mouseenterindex != index)
                {
                    this.mouseenterindex = index;
                    this.Invalidate();
                }
            }

        }
        /// <summary>
        /// 鼠标滚轮滚动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmMouseWheel(object sender, MouseEventArgs e)
        {
            int offset = this.scrollOffsetY + (e.Delta / 120 * this.item_height / 2);
            this.SetScrollOffsetY(offset);
        }
        /// <summary>
        /// 主题面板弹层关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmClosed(object sender, EventArgs e)
        {
            Debug.Print("Closed " + DateTime.Now.ToString("时间[ HH:mm:ss fff ]"));

            this.HidePicker();
        }
        /// <summary>
        /// 绘制（模仿非工作区）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmNCPaint(object sender, PaintEventArgs e)
        {
            //阴影
            e.Graphics.DrawImageUnscaled(this.shadow_image_tmp, new Point(0, 0));
        }
        /// <summary>
        /// 绘制（模仿工作区）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmPaint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            int scale_roundSize = (int)Math.Ceiling(this.RoundSize * this.ScaleDpi);
            Size scale_itemColorSize = new Size(this.font_height + this.font_height / 2, this.font_height + this.font_height / 2);
            Size scale_itemSelectedSize = new Size(this.font_height + this.font_height / 2, this.font_height + this.font_height / 2);
            int scale_scrollThickness = (int)(this.ScrollBar.TrackThickness * this.ScaleDpi);
            int item_start_index = this.GetClientRectangleFirstIndex();

            // 背景
            SolidBrush back_sb = new SolidBrush(this.ItemsSource.Count == 0 ? this.StyleAppearance.NullTipBackColor : this.StyleAppearance.BackColor);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillRectangle(back_sb, this.ClientRectangle);
            g.SmoothingMode = SmoothingMode.Default;
            back_sb.Dispose();

            //选项
            SolidBrush commom_sb = new SolidBrush(Color.White);
            int index = -1;
            foreach (KeyValuePair<string, Color> item in this.ItemsSource)
            {
                index += 1;
                int top = this.ClientRectangle.Y + this.scrollOffsetY + index * this.item_height;
                int bottom = top + this.item_height;
                if (bottom >= this.ClientRectangle.Y)
                {
                    if (top > this.ClientRectangle.Bottom)
                        break;

                    Rectangle item_rect = new Rectangle(this.ClientRectangle.X, top, this.ClientRectangle.Width, this.item_height);
                    Rectangle item_color_rect = new Rectangle(item_rect.X + scale_roundSize + this.font_height / 2, item_rect.Y + (item_rect.Height - scale_itemColorSize.Height) / 2, scale_itemColorSize.Width, scale_itemColorSize.Height);
                    Rectangle item_selected_rect = new Rectangle(item_rect.Right - Math.Max(scale_roundSize, (this.ScrollVisible ? this.scrollTrackRect.Width : 0)) - scale_itemSelectedSize.Width * 2, item_rect.Y + (item_rect.Height - scale_itemSelectedSize.Height) / 2, scale_itemSelectedSize.Width, scale_itemSelectedSize.Height);
                    Size item_text_size = new Size((int)Math.Ceiling(g.MeasureString(item.Key, this.Font, int.MaxValue, StringFormat.GenericTypographic).Width), this.font_height);
                    Rectangle item_text_rect = new Rectangle((item_color_rect.Right + this.font_height), item_rect.Y + (item_rect.Height - item_text_size.Height) / 2, item_text_size.Width, item_text_size.Height);

                    // 选项背景
                    commom_sb.Color = (this.mouseenterindex == index) ? this.StyleAppearance.Item.Enter.BackColor : this.StyleAppearance.Item.Normal.BackColor;
                    g.FillRectangle(commom_sb, item_rect);

                    // 颜色
                    commom_sb.Color = item.Value;
                    g.FillRectangle(commom_sb, item_color_rect);

                    // 选项文本
                    commom_sb.Color = (this.mouseenterindex == index) ? this.StyleAppearance.Item.Enter.TextColor : this.StyleAppearance.Item.Normal.TextColor;

                    g.DrawString(item.Key, this.Font, commom_sb, item_text_rect.Location, StringFormat.GenericTypographic);
                    // 选中钩
                    if (this.selectedItem != null && this.selectedItem == item.Key)
                    {

                        float min_grid = scale_itemSelectedSize.Width / 10f;
                        PointF[] check_char_line = new PointF[] {
                        new PointF(item_selected_rect.X+min_grid,item_selected_rect.Y+ min_grid * 4.5f),
                        new PointF(item_selected_rect.X+min_grid *4,item_selected_rect.Y+  min_grid * 7),
                        new PointF(item_selected_rect.X+min_grid*8f ,item_selected_rect.Y+  min_grid*2)
                        };

                        g.SmoothingMode = SmoothingMode.AntiAlias;

                        Pen selected_pen = new Pen(this.StyleAppearance.SymbolColor, scale_itemSelectedSize.Width / 7f);
                        g.DrawLines(selected_pen, check_char_line);
                        selected_pen.Dispose();

                        g.SmoothingMode = SmoothingMode.Default;

                    }

                }
            }
            commom_sb.Dispose();

            // 滚动条
            if (this.ScrollVisible)
            {
                SolidBrush track_back_sb = new SolidBrush(this.StyleAppearance.ScrollBar.TrackBackColor);
                Pen thumb_back_pen = new Pen(this.StyleAppearance.ScrollBar.ThumbBackColor, scale_scrollThickness);

                // 轨道
                g.FillRectangle(track_back_sb, this.scrollTrackRect);
                // 拇指
                PointF sp_start = new PointF(this.scrollThumbRect.X + scale_scrollThickness / 2, this.scrollThumbRect.Y);
                PointF sp_end = new PointF(this.scrollThumbRect.X + scale_scrollThickness / 2, this.scrollThumbRect.Bottom);
                g.DrawLine(thumb_back_pen, sp_start, sp_end);

                track_back_sb.Dispose();
                thumb_back_pen.Dispose();
            }

            //空列表文本提示
            if (this.ItemsSource.Count == 0)
            {
                Size nullitemstiptext_size = new Size((int)Math.Ceiling(g.MeasureString(this.NullTipText, this.Font, int.MaxValue, StringFormat.GenericTypographic).Width), this.font_height);
                SolidBrush nullitemstiptext_sb = new SolidBrush(this.StyleAppearance.NullTipTextColor);
                g.DrawString(this.NullTipText, this.Font, nullitemstiptext_sb, new RectangleF(this.ClientRectangle.X + (this.ClientRectangle.Width - nullitemstiptext_size.Width) / 2, this.ClientRectangle.Y + (this.ClientRectangle.Height - nullitemstiptext_size.Height) / 2, nullitemstiptext_size.Width, nullitemstiptext_size.Height), StringFormat.GenericTypographic);
                nullitemstiptext_sb.Dispose();
            }

        }
        /// <summary>
        /// 绘制（边框）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WmBorderPaint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            // 边框
            int scale_roundedCorner = (int)Math.Ceiling(this.RoundSize * this.ScaleDpi);
            GraphicsPath border_path = ControlHelper.AdjustCircularPath(this.ClientRectangle, scale_roundedCorner);
            Pen border_pen = new Pen(this.StyleAppearance.BorderColor, 1);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.DrawPath(border_pen, border_path);
            g.SmoothingMode = SmoothingMode.Default;
            border_pen.Dispose();
            border_path.Dispose();
        }

        #endregion

        //GC调用的析构函数
        ~SkinPicker()
        {
            Dispose(false);//释放非托管资源
        }

        #region 类

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class ScrollBarObject
        {
            private SkinPicker owner = null;
            internal ScrollBarObject(SkinPicker owner) { this.owner = owner; }

            #region 属性

            private int trackThickness = 12;
            /// <summary>
            /// 轨道厚度
            /// </summary>
            [Description("轨道厚度")]
            [PropertyOrder(-140)]
            [DefaultValue(12)]
            public int TrackThickness
            {
                get { return this.trackThickness; }
                set
                {
                    if (this.trackThickness == value || value < 0)
                        return;

                    this.trackThickness = value;
                }
            }

            private int thumbMinSize = 26;
            /// <summary>
            /// 拇指最小高度
            /// </summary>
            [Description("拇指最小高度")]
            [PropertyOrder(-138)]
            [DefaultValue(26)]
            public int ThumbMinSize
            {
                get { return this.thumbMinSize; }
                set
                {
                    if (this.thumbMinSize == value || value < 1)
                        return;

                    this.thumbMinSize = value;
                }
            }

            #endregion

        }

        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinBorderColor = Color.Empty;
            private readonly Color defaultBorderColor = SystemColors.ActiveCaption;
            private Color borderColor = Color.Empty;
            /// <summary>
            /// 边框颜色
            /// </summary>
            [Description("边框颜色")]
            [PropertyOrder(-159)]
            [SkinProperty(true, false)]
            public Color BorderColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinBorderColor;
                    }

                    if (this.borderColor != Color.Empty)
                    {
                        return this.borderColor;
                    }

                    return this.defaultBorderColor;
                }
                set
                {
                    if (this.borderColor == value)
                        return;

                    this.borderColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeBorderColor()
            {
                return this.borderColor != Color.Empty;
            }
            private void ResetBorderColor()
            {
                this.borderColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinBackColor = Color.Empty;
            private readonly Color defaultBackColor = SystemColors.Window;
            private Color backColor = Color.Empty;
            /// <summary>
            /// 背景颜色
            /// </summary>
            [Description("背景颜色")]
            [PropertyOrder(-158)]
            [SkinProperty(true, false)]
            public Color BackColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinBackColor;
                    }

                    if (this.backColor != Color.Empty)
                    {
                        return this.backColor;
                    }

                    return this.defaultBackColor;
                }
                set
                {
                    if (this.backColor == value)
                        return;

                    this.backColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeBackColor()
            {
                return this.backColor != Color.Empty;
            }
            private void ResetBackColor()
            {
                this.backColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinShadowColor = Color.Empty;
            private readonly Color defaultShadowColor = Color.Empty;
            private Color shadowColor = Color.Empty;
            /// <summary>
            /// 四周阴影颜色
            /// </summary>
            [Description("四周阴影颜色")]
            [PropertyOrder(-194)]
            [SkinProperty(true, false)]
            public Color ShadowColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinShadowColor;
                    }

                    if (this.shadowColor != Color.Empty)
                    {
                        return this.shadowColor;
                    }

                    return this.defaultShadowColor;
                }
                set
                {
                    if (this.shadowColor == value)
                        return;

                    this.shadowColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeShadowColor()
            {
                return this.shadowColor != Color.Empty;
            }
            private void ResetShadowColor()
            {
                this.shadowColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinSymbolColor = Color.Empty;
            private readonly Color defaultSymbolColor = SystemColors.ActiveCaption;
            private Color symbolColor = Color.Empty;
            /// <summary>
            /// 选中选项钩颜色
            /// </summary>
            [Description("选中选项钩颜色")]
            [PropertyOrder(-197)]
            [SkinProperty(true, false)]
            public Color SymbolColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinSymbolColor;
                    }

                    if (this.symbolColor != Color.Empty)
                    {
                        return this.symbolColor;
                    }

                    return this.defaultSymbolColor;
                }
                set
                {
                    if (this.symbolColor == value)
                        return;

                    this.symbolColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeSymbolColor()
            {
                return this.symbolColor != Color.Empty;
            }
            private void ResetSymbolColor()
            {
                this.symbolColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinNullTipBackColor = Color.Empty;
            private readonly Color defaultNullTipBackColor = SystemColors.Window;
            private Color nullTipBackColor = Color.Empty;
            /// <summary>
            /// 空数据源提示背景颜色
            /// </summary>
            [Description("空数据源提示背景颜色")]
            [PropertyOrder(-185)]
            [SkinProperty(true, false)]
            public Color NullTipBackColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinNullTipBackColor;
                    }

                    if (this.nullTipBackColor != Color.Empty)
                    {
                        return this.nullTipBackColor;
                    }

                    return this.defaultNullTipBackColor;
                }
                set
                {
                    if (this.nullTipBackColor == value)
                        return;

                    this.nullTipBackColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeNullTipBackColor()
            {
                return this.nullTipBackColor != Color.Empty;
            }
            private void ResetNullTipBackColor()
            {
                this.nullTipBackColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinNullTipTextColor = Color.Empty;
            private readonly Color defaultNullTipTextColor = Color.Tomato;
            private Color nullTipTextColor = Color.Empty;
            /// <summary>
            /// 空数据源提示文本颜色
            /// </summary>
            [Description("空数据源提示文本颜色")]
            [PropertyOrder(-184)]
            [SkinProperty(true, false)]
            public Color NullTipTextColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinNullTipTextColor;
                    }

                    if (this.nullTipTextColor != Color.Empty)
                    {
                        return this.nullTipTextColor;
                    }

                    return this.defaultNullTipTextColor;
                }
                set
                {
                    if (this.nullTipTextColor == value)
                        return;

                    this.nullTipTextColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeNullTipTextColor()
            {
                return this.nullTipTextColor != Color.Empty;
            }
            private void ResetNullTipTextColor()
            {
                this.nullTipTextColor = Color.Empty;
                this.Invalidate();
            }

            private ItemObjectAppearanceObject item;
            /// <summary>
            /// 选项
            /// </summary>
            [Description("选项")]
            [PropertyOrder(-180)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public ItemObjectAppearanceObject Item
            {
                get
                {
                    if (this.item == null)
                        this.item = new ItemObjectAppearanceObject(this.owner, this);
                    return this.item;
                }
            }

            private ScrollBarAppearanceObject scrollBar;
            /// <summary>
            /// 滚动条
            /// </summary>
            [Description("滚动条")]
            [PropertyOrder(-178)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public ScrollBarAppearanceObject ScrollBar
            {
                get
                {
                    if (this.scrollBar == null)
                        this.scrollBar = new ScrollBarAppearanceObject(this.owner, this);
                    return this.scrollBar;
                }
            }

            #endregion

            public class ItemObjectAppearanceObject : AppearanceObjectBase
            {
                internal ItemObjectAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private ItemAppearanceObject normal;
                /// <summary>
                /// 正常状态
                /// </summary>
                [Description("正常状态")]
                [PropertyOrder(-194)]
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
                [SkinProperty(true, false)]
                public ItemAppearanceObject Normal
                {
                    get
                    {
                        if (this.normal == null)
                            this.normal = new ItemAppearanceObject(this.owner, this, Color.Empty, SystemColors.ControlText);
                        return this.normal;
                    }
                }

                private ItemAppearanceObject enter;
                /// <summary>
                /// 鼠标进入状态
                /// </summary>
                [Description("鼠标进入状态")]
                [PropertyOrder(-192)]
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
                [SkinProperty(true, false)]
                public ItemAppearanceObject Enter
                {
                    get
                    {
                        if (this.enter == null)
                            this.enter = new ItemAppearanceObject(this.owner, this, SystemColors.GradientInactiveCaption, SystemColors.Window);
                        return this.enter;
                    }
                }

                #endregion

                public class ItemAppearanceObject : AppearanceObjectBase
                {
                    internal ItemAppearanceObject(ISkinObject owner, AppearanceObjectBase parent, Color backColor, Color textColor) : base(owner, parent)
                    {
                        this.defaultBackColor = backColor;
                        this.defaultTextColor = textColor;
                    }

                    #region 属性

                    private Color skinBackColor = Color.Empty;
                    private readonly Color defaultBackColor = Color.Empty;
                    private Color backColor = Color.Empty;
                    /// <summary>
                    /// 背景颜色
                    /// </summary>
                    [Description("背景颜色")]
                    [PropertyOrder(-158)]
                    [SkinProperty(true, false)]
                    public Color BackColor
                    {
                        get
                        {
                            if (this.owner.GetSkinObjectSkinStateCore())
                            {
                                return this.skinBackColor;
                            }

                            if (this.backColor != Color.Empty)
                            {
                                return this.backColor;
                            }

                            return this.defaultBackColor;
                        }
                        set
                        {
                            if (this.backColor == value)
                                return;

                            this.backColor = value;
                            this.Invalidate();
                        }
                    }
                    private bool ShouldSerializeBackColor()
                    {
                        return this.backColor != Color.Empty;
                    }
                    private void ResetBackColor()
                    {
                        this.backColor = Color.Empty;
                        this.Invalidate();
                    }

                    private Color skinTextColor = Color.Empty;
                    private readonly Color defaultTextColor = Color.Empty;
                    private Color textColor = Color.Empty;
                    /// <summary>
                    /// 文本颜色
                    /// </summary>
                    [Description("文本颜色")]
                    [PropertyOrder(-157)]
                    [SkinProperty(true, false)]
                    public Color TextColor
                    {
                        get
                        {
                            if (this.owner.GetSkinObjectSkinStateCore())
                            {
                                return this.skinTextColor;
                            }

                            if (this.textColor != Color.Empty)
                            {
                                return this.textColor;
                            }

                            return this.defaultTextColor;
                        }
                        set
                        {
                            if (this.textColor == value)
                                return;

                            this.textColor = value;
                            this.Invalidate();
                        }
                    }
                    private bool ShouldSerializeTextColor()
                    {
                        return this.textColor != Color.Empty;
                    }
                    private void ResetTextColor()
                    {
                        this.textColor = Color.Empty;
                        this.Invalidate();
                    }

                    #endregion

                }

            }

            public class ScrollBarAppearanceObject : AppearanceObjectBase
            {
                internal ScrollBarAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private Color skinTrackBackColor = Color.Empty;
                private readonly Color defaultTrackBackColor = SystemColors.ScrollBar;
                private Color trackBackColor = Color.Empty;
                /// <summary>
                /// 轨道背景颜色
                /// </summary>
                [Description("轨道背景颜色")]
                [PropertyOrder(-139)]
                [SkinProperty(true, false)]
                public Color TrackBackColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinTrackBackColor;
                        }

                        if (this.trackBackColor != Color.Empty)
                        {
                            return this.trackBackColor;
                        }

                        return this.defaultTrackBackColor;
                    }
                    set
                    {
                        if (this.trackBackColor == value)
                            return;

                        this.trackBackColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeTrackBackColor()
                {
                    return this.trackBackColor != Color.Empty;
                }
                private void ResetTrackBackColor()
                {
                    this.trackBackColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinThumbBackColor = Color.Empty;
                private readonly Color defaultThumbBackColor = SystemColors.WindowFrame;
                private Color thumbBackColor = Color.Empty;
                /// <summary>
                /// 拇指背景颜色
                /// </summary>
                [Description("拇指背景颜色")]
                [PropertyOrder(-134)]
                [SkinProperty(true, false)]
                public Color ThumbBackColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinThumbBackColor;
                        }

                        if (this.thumbBackColor != Color.Empty)
                        {
                            return this.thumbBackColor;
                        }

                        return this.defaultThumbBackColor;
                    }
                    set
                    {
                        if (this.thumbBackColor == value)
                            return;

                        this.thumbBackColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeThumbBackColor()
                {
                    return this.thumbBackColor != Color.Empty;
                }
                private void ResetThumbBackColor()
                {
                    this.thumbBackColor = Color.Empty;
                    this.Invalidate();
                }

                #endregion

            }

        }

        #endregion

    }

}
